package com.example.common.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

/**
 * AES 加密、解密 工具类
 *
 * @author zhoubin
 * @date 2019-05-27 11:01:09
 */
public class AESUtil {

    /**
     * 密钥算法
     */
    public static final String AES_ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    public static final String CIPHER_ALGORITHM_PKCS5 = "AES/ECB/PKCS5Padding";

//    /**
//     * 加密/解密算法 / 工作模式 / 填充方式
//     * Java 6支持PKCS5Padding填充方式
//     * Bouncy Castle支持PKCS7Padding填充方式
//     */
//    private static final String CIPHER_ALGORITHM_PKCS7 = "AES/ECB/PKCS7Padding";


    /**
     * 默认 aes 密钥长度
     */
    public static final int defaultLength = 16;

    /**
     * 密钥长度
     */
    public static final int SECRET_KEY_LENGTH_128 = 128;
    public static final int SECRET_KEY_LENGTH_192 = 192;
    public static final int SECRET_KEY_LENGTH_256 = 256;

    /**
     * 随机生成AES加密秘钥
     * 密钥长度为 16 位
     *
     * @return
     */
    public static String getKey() {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < 16; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                result += (char) (random.nextInt(26) + temp);
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                result += String.valueOf(random.nextInt(10));
            }
        }
        return result;
    }

    /**
     * 获取 AES 的密钥(byte类型经过 base64 转字符串)
     *
     * @return
     */
    public static String getAesKey() {
        String result = "";
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
            keyGenerator.init(SECRET_KEY_LENGTH_128);
            SecretKey secretKey = keyGenerator.generateKey();
            result = Base64.encodeBase64String(secretKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 加密
     *
     * @param plainText 明文
     * @param keyStr    加密密钥
     * @return
     */
    public static String encrypt(String plainText, String keyStr) {

        String encryptStr = null;

        try {
            Key key = new SecretKeySpec(Base64.decodeBase64(keyStr), AES_ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 加密
            byte[] result = cipher.doFinal(plainText.getBytes());
            encryptStr = Base64.encodeBase64String(result);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return encryptStr;
    }


    /**
     * 解密
     *
     * @param encryptData 加密数据
     * @param keyStr      解密密钥
     * @return
     */
    public static String decrypt(String encryptData, String keyStr) {

        String decryptStr = null;
        try {
            Key key = new SecretKeySpec(Base64.decodeBase64(keyStr), AES_ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
            cipher.init(Cipher.DECRYPT_MODE, key);
            decryptStr = new String(cipher.doFinal(Base64.decodeBase64(encryptData)));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decryptStr;
    }


    public static void main(String[] args) {

        String plainText = "{\"code\":\"000000\",\"data\":{\"bankUserId\":\"00000845\",\"bankCardNo\":\"6225880163481147\",\"bankName\":\"招商银行\",\"telephone\":\"18910657501\",\"imageStatus\":\"UPLOADED\",\"openAccountTime\":\"2019-04-30 14:58:10\",\"acNo\":\"627078990000005099\",\"status\":\"OPENED\"},\"message\":\"SUCCESS\"}";
        String key = getAesKey();
        System.out.println("加密key:" + key);
        String encryptData = encrypt(plainText, key);
        System.out.println("加密数据:" + encryptData);
        System.out.println("解密数据:" + decrypt(encryptData, key));

//        System.out.println("明文加密key:"+getKey());

    }

}
